home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / gle / util / manip / cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-29  |  27.9 KB  |  1,256 lines

  1. /*    number    - put it in current cell and move in current dir
  2.     'string   - put string in cell and move in current direction
  3.     range = expression  - evaluate exp for each cell in range
  4.     cell(exp,exp) = expression  - evaluate exp and put in cell
  5.     cmd    - exectue command, if then else next for save load generate
  6.                    print, input
  7.     & = continued on next line.
  8.  
  9.     load b.dat  range c3r3   width 10.3  between ", "
  10.     save b.c  c3c4
  11.     set outwidth 0
  12.     set outwidth 10.3
  13.     set between ", "
  14.     copy c1 c2
  15. */
  16.  
  17. #include "all.h"
  18. #include <math.h>
  19. #include <time.h>
  20. #include "edt.h"
  21. #include "keyword.h"
  22. int range_next(RANGE *r);
  23. int range_def(char *s, RANGE *r);
  24. int sort_shuffle(int i, int r1, int *pnt);
  25. int m_tokinit(char *termset);
  26. int passcmd(char *source,char *tk[],int *ntok);
  27. int do_assign(char *t1, char *t2);
  28. extern int in_recover;
  29. extern int curx;
  30. extern int cury;
  31. extern int max_x,max_y;
  32. #define tok(j) (tk[j])
  33. #define dbg if (gle_debug>0)
  34. extern char file_name[];
  35. extern int iserr;
  36. extern int gle_debug,changed;
  37. extern int trace_on;
  38. extern int exit_manip;
  39. int isating;
  40. int islogging;
  41. int load_list;
  42. int dpoints[200];
  43. int coltype[200];
  44. int outwidth1=8,outwidth2=8;
  45. char *between=" ";
  46. char strmiss[40];
  47. /*---------------------------------------------------------------------------*/
  48. do_command(char *cmd)
  49. {
  50.     static char inbuff[200];
  51.     static char *tk[500];
  52.     static char tkbuff[500];
  53.     int j,i,al,ntok,f;
  54.     static char space_str[] = " ";
  55.  
  56.     if (islogging) log_write(cmd);
  57.     
  58.     token_space();
  59.     strcat(inbuff,cmd);
  60.     al = strlen(inbuff);
  61.     if (inbuff[al-1]=='&') {
  62.         inbuff[al-1] = 0;
  63.         return;
  64.     }
  65.     token(inbuff,tk,&ntok,tkbuff);
  66.     for (i=ntok+1;i< ntok+5;i++) tk[i] = space_str;
  67. /*     for (i=1;i<=ntok;i++) printf("token{%s} ",tk[i]);
  68.      printf("\n"); */
  69.     passcmd(inbuff,tk,&ntok);
  70.     inbuff[0] = 0;
  71.  
  72. }
  73.  
  74. extern int moving_x, moving_y;
  75.  
  76.  
  77. passcmd(char *source,char *tk[],int *ntok)
  78. {
  79.     int j,etype,sub_start,sub_end,i,f,np,ix,vidx,vtype=1;
  80.     double v;
  81.     char *sp;
  82.     etype = 1;
  83.     find_mkey(tok(1),&ix);
  84.     if (strcmp(tok(2),"=")==0)  {
  85.         do_assign(tok(1),tok(3));
  86.         return;
  87.     }
  88.     sp = strchr(tok(1),'=');
  89.     if (sp!=NULL) {
  90.         *sp = 0;
  91.         do_assign(tok(1),sp+1);
  92.         return;
  93.     }
  94.     if (isnumber(tok(1)) || *tok(1)=='-') {
  95.         set_cell(curx,cury,atof(tok(1)));
  96.         set_newxy(curx+moving_x,cury+moving_y);
  97.         return;
  98.         }
  99.     if ((*tok(1))=='"') {
  100.         *(tok(1)+strlen(tok(1))-1) = 0;
  101.         set_scell(curx,cury,tok(1)+1);
  102.         set_newxy(curx+moving_x,cury+moving_y);
  103.         return;
  104.         }
  105.     if ((*tok(1))=='@') {
  106.         at_open(tok(1)+1);
  107.         return;
  108.     }
  109.     switch (ix) {
  110.       case k_data: /* data <range> */
  111.         cmd_data(tok(2));
  112.         break;
  113.       case k_help:/* help load */
  114.         if (*ntok==1) do_help("MANIP","");
  115.         else do_help(tok(2),tok(3));
  116.         refresh();
  117.         break;
  118.       case k_list: /* list a.a [range] , reads a list of numbers */
  119.         load_list = true;
  120.         cmd_load(tok(2),tok(3),*ntok);
  121.         load_list = false;
  122.         break;
  123.       case k_load: /* LOAD  A.A  [range] -LIST */
  124.         if (*ntok>3) if (strcmp(tok(4),"-LIST")==0) load_list = true;
  125.         cmd_load(tok(2),tok(3),*ntok);
  126.         load_list = false;
  127.         break;
  128.       case k_save: /* SAVE [a.a] [range] [format-string] */
  129.         changed = false;
  130.         cmd_save(tok(2),tok(3),tok(4),*ntok);
  131.         break;
  132.       case k_set: /* set outwidth, set width, set between, */
  133.         if (strcmp(tok(2),"OUTWIDTH")==0) set_outwidth(tok(3));
  134.         else if (strcmp(tok(2),"WIDTH")==0) set_outwidth(tok(3));
  135.         else if (strcmp(tok(2),"BETWEEN")==0) between = unquote(tok(3));
  136.         else if (strcmp(tok(2),"MISSING")==0) strcpy(strmiss,unquote(tok(3)));
  137.         else if (strcmp(tok(2),"DIGITS")==0) outwidth2 = atoi(tok(3));
  138.         else if (strcmp(tok(2),"DPOINTS")==0) {
  139.             i = atoi(tok(3));
  140.             if (*ntok>3) dpoints[atoi(tok(4))] = i;
  141.             else for (j=0;j<200;j++) dpoints[j] = i;
  142.         }
  143.         else if (strcmp(tok(2),"COLTYPE")==0) {
  144.             i = atoi(tok(3));
  145.             if (*tok(3)=='C') i = atoi(tok(3)+1);
  146.             if (strcmp(tok(4),"BOTH")==0) j = 0;
  147.             if (strcmp(tok(4),"DECIMAL")==0) j = 1;
  148.             if (strcmp(tok(4),"EXP")==0) j = 2;
  149.             if (strcmp(tok(4),"DPOINTS")==0) {
  150.                 j = atoi(tok(5));
  151.                 if (i==0) for (i=0;i<200;i++) dpoints[i] = j;
  152.                 else dpoints[i] = j;
  153.             } else {
  154.                 if (i==0) for (i=0;i<200;i++) coltype[i] = j;
  155.                 else coltype[i] = j;
  156.             }
  157.         }
  158.         else if (strcmp(tok(2),"COLUMNS")==0) set_ncol(atoi(tok(3)));
  159.         else if (strcmp(tok(2),"NCOL")==0) set_ncol(atoi(tok(3)));
  160.         else if (strcmp(tok(2),"COLWIDTH")==0) set_colwidth(atoi(tok(3)));
  161.         else if (strcmp(tok(2),"PRECISION")==0) outwidth2 = atoi(tok(3));
  162.         else if (strcmp(tok(2),"SIZE")==0) {
  163.             set_size(atoi(tok(3)),atoi(tok(4)));
  164.         }
  165.         else fner("Invalid SET command, Use (width,between,digits,dpoints,ncol,colwidth)\n");
  166.         break;
  167.       case k_new: /* clears the spreadsheet and free's memory */
  168.         clear_data();
  169.         break;
  170.       case k_clear: /* clear part of the spread sheet */
  171.         cmd_clear(tok(2));
  172.         break;
  173.       case k_delete: /* delete <range> [if <exp>] */
  174.         cmd_delete(tok(2),tok(4),*ntok);
  175.         trim_data();
  176.         break;
  177.       case k_insert: /* insert <range> */
  178.         cmd_insert(tok(2));
  179.         break;
  180.       case k_exit:
  181.         cmd_save(tok(2),tok(3),tok(4),*ntok);
  182.         changed = false;
  183.         exit_manip = true;
  184.         break;
  185.       case k_quit:
  186.         exit_manip = true;
  187.         break;
  188.       case k_logging: /* log filename */
  189.         if (islogging) log_close();
  190.         log_open(tk[2]);
  191.         break;
  192.       case k_close:
  193.         log_close();
  194.         break;
  195.       case k_at: /* execute file of manip commands */
  196.         at_open(tk[2]);
  197.         break;
  198.       case k_call:
  199.         refresh();
  200.         break;
  201.       case k_sort: /* sort <range> on <exp> */
  202.         cmd_sort(tk[2],tk[4],*ntok);
  203.         break;
  204.       case k_swap: /* swap CaCb  || swap RaRb */
  205.         cmd_swap(tk[2]);
  206.         break;
  207.       case k_shell:
  208.         window(1,1,80,25); scr_norm(); clrscr();
  209.         printf("Type in EXIT to return to MANIP\n\n");
  210.         system("");
  211.         refresh();
  212.         break;
  213.       case k_sum:
  214.         cmd_sum(tk[2]);
  215.         break;
  216.       case k_fit:
  217.         cmd_fit(tk[2]);
  218.         break;
  219.       case k_parsum:
  220.         cmd_parsum(tk[2],tk[3]);
  221.         break;
  222.       case k_if:
  223.       case k_else:
  224.       case k_end:
  225.       case k_for:
  226.       case k_next:
  227.       case k_print:
  228.       case k_input: /* input "prompt" variable */
  229.       case k_copy: /* copy range1  range2  [if exp] (doesn't) */
  230.         cmd_copy(tk[2],tk[3],tk[5],*ntok,true);
  231.         break;
  232.       case k_move: /* move range1  range2  [if exp] (leaves gaps) */
  233.         cmd_copy(tk[2],tk[3],tk[5],*ntok,false);
  234.         break;
  235.       case k_prop: /* prop range1  range2  (cycle thru range1)  */
  236.         cmd_copy(tk[2],tk[3],tk[5],*ntok,2);
  237.         break;
  238.       case k_generate: /* gen 2(1,2:4)3  c1  (1 1 2 2 3 3 4 4) 3 times*/
  239.         cmd_generate(tk[2],tk[3],*ntok);
  240.         break;
  241.       case k_let:
  242.         /* let variable = expression */
  243.         var_findadd(tk[2],&vidx,&vtype);
  244.         evaluate(tk[4],&v);
  245.         var_set(vidx,v);
  246.         break;
  247.       case k_goto: /* should really use eval, not atoi so var's work */
  248.         set_newxy(atoi(tk[2]),atoi(tk[3]));
  249.         break;
  250.       default:
  251.         fner("No such command {%s} {%s}\n",tk[1],tk[2]);
  252.     }
  253. }
  254. struct op_key { char *name; int typ; int pos; long idx; } ;
  255. typedef struct op_key (*OPKEY)[100];
  256.  
  257.  
  258. do_assign(char *t1, char *t2)
  259. {
  260.     RANGE rr;
  261.     int cp,vtype,vidx;
  262.     double v;
  263.     static long pcode[200];
  264.     static char outstr[80];
  265.     int plen;
  266.     vtype = 1;
  267.  
  268.         /* ------------------         */
  269.         /* variable = expression     */
  270.         /* cell(exp,exp) = exp         */
  271.         /* range = exp             */
  272.         /* ------------------         */
  273.  
  274.     if (strncmp(t1,"CELL(",5)==0) {        /* cell(exp,exp) = exp */
  275.       {     char s1[80],s2[80],*s;
  276.         int x,y;
  277.         s = strchr(t1,',');
  278.         if (s==NULL) {
  279.             fner("Expecting CELL(EXP,EXP) = EXP \n");
  280.             return;
  281.         }
  282.         strcpy(s1,t1+5); strcpy(s2,s+1);
  283.         *strchr(s1,',') = 0;
  284.         if (strchr(s2,')')!=NULL) *strchr(s2,')') = 0;
  285.         evaluate(s1,&v); x = v;
  286.         evaluate(s2,&v); y = v;
  287.         evaluate(t2,&v);
  288.         set_cell(x,y,v);
  289.         show_ifcell(x,y);
  290.       }
  291.       return;
  292.     }
  293.     if (range_def(t1,&rr)) {                   /* range = exp */
  294.      {
  295.        int c_idx[20], c_val[20], nc, j;
  296.        int r_idx[20], r_val[20], nr;
  297.  
  298.         polish(t2,(char *) pcode,&plen,&vtype);
  299.         var_find_rc(c_idx,c_val,&nc,'C');
  300.         var_find_rc(r_idx,r_val,&nr,'R');
  301.         for (;range_next(&rr);) {
  302.             cp = 0;
  303.             eval_setxy(rr.col,rr.row);
  304.             for (j=0;j<nc;j++) {
  305.                 var_set(c_idx[j],vcell(c_val[j],rr.row));
  306.             }
  307.             for (j=0;j<nr;j++) {
  308.                 var_set(r_idx[j],vcell(rr.col,r_val[j]));
  309.             }
  310.             eval(pcode,&cp,&v,outstr,&vtype);
  311.             set_cell(rr.col,rr.row,v);
  312.             show_ifcell(rr.col,rr.row);
  313.         }
  314.         return;
  315.      }
  316.     }
  317.     fner("error, expecting cell(exp,exp) = exp, or range = exp \n");
  318. }
  319. evaluate(char *exp, double *v)
  320. {
  321.     static long pcode[200];
  322.     int plen,vtype,cp;
  323.     static char outstr[100];
  324.  
  325.     vtype = 1;
  326.     polish(exp,(char *) pcode,&plen,&vtype);
  327.     if (plen>150) fner("pcode too long, report bug to Chris\n");
  328.     cp = 0;
  329.     eval(pcode,&cp,v,outstr,&vtype);
  330. }
  331. int new_line;
  332. range_next(RANGE *r)
  333. {
  334.     new_line = false;
  335.     if (r->row==0) {
  336.         r->row = r->r1; r->col = r->c1;
  337.         return true;
  338.     }
  339.     if (r->colfirst) {
  340.         r->col++;
  341.         if (r->col > r->c2) {
  342.             new_line = true;
  343.             r->col = r->c1;
  344.             r->row++;
  345.             if (r->row > r->r2) return false;
  346.         }
  347.     } else {
  348.         r->row++;
  349.         if (r->row > r->r2) {
  350.             new_line = true;
  351.             r->row = r->r1;
  352.             r->col++;
  353.             if (r->col > r->c2) return false;
  354.         }
  355.     }
  356.     return true;
  357. }
  358. range_def(char *sxx, RANGE *r)
  359. {
  360.   char s[80];
  361.     char *s1;
  362.     char rr,cc;
  363.   strcpy(s,sxx);
  364.     strip_colon(s);
  365.     r->c1 = r->c2 = r->r1 = r->r2 = r->row = r->col = 0;
  366.  
  367.     if (*s=='C') {cc='C'; rr='R'; r->colfirst = true;}
  368.     else if (*s=='R') {cc='R'; rr='C'; r->colfirst = false;}
  369.     else return false;
  370. /*    c1   c1r1r10   c3c4r7 c3r7  c3c4r1r2 |   r1r2c1c3   c3r7  r2*/
  371.  
  372.     s1 = range_int(s,&(r->c1));
  373.     if (*s1==cc) {
  374.         s1 = range_int(s1,&r->c2);
  375.     }
  376.     if (*s1==rr) {
  377.         s1 = range_int(s1,&r->r1);
  378.         if (*s1==cc) {
  379.             s1 = range_int(s1,&r->c2);
  380.         }
  381.         if (*s1==rr) {
  382.             s1 = range_int(s1,&r->r2);
  383.         }
  384.         if (*s1==cc) {
  385.             s1 = range_int(s1,&r->c2);
  386.         }
  387.     }
  388.     if (!r->colfirst) {
  389.         swapint(&r->c1,&r->r1);
  390.         swapint(&r->c2,&r->r2);
  391.     }
  392.     if (r->c1 == 0) r->c1 = 1;
  393.     if (r->c2 == 0) {
  394.       if (!r->colfirst) {
  395.         if (r->c1 > max_x) r->c2 = r->c1; else r->c2 = max_x;
  396.       } else {
  397.         r->c2 = r->c1;
  398.       }
  399.     }
  400.     if (r->r1 == 0) r->r1 = 1;
  401.     if (r->r2 == 0) {if (r->colfirst)
  402.         { if (r->r1>max_y) r->r2 = r->r1; else r->r2 = max_y;}
  403.       else r->r2 = r->r1;}
  404.  
  405. /*       printf("range def %d %d   %d %d  | \n",r->c1,r->r1,r->c2,r->r2); getch();*/
  406.     data_expand(r->c2,r->r2);
  407.     if (*s1!=0) return false;
  408.     return true;
  409. }
  410. char *range_int(char *s, int *v)
  411. {
  412.     static char buff[40],*b;
  413.     b = buff;
  414.     for (s++;*s!=0 && isdigit(*s);)
  415.         *b++ = *s++;
  416.     *b++ = 0;
  417.     *v = atoi(buff);
  418.     return s;
  419. }
  420. swapint(int *a, int *b)
  421. {
  422.     int c;
  423.     c = *a;
  424.     *a = *b;
  425.     *b = c;
  426. }
  427. char *sep_chars=", \t\n";
  428. cmd_load(char *fname, char *range, int ntok)
  429. {
  430.     RANGE rr;
  431.     static char inbuff[8001];
  432.     FILE *fptr;
  433.     int i;
  434.     
  435.     m_tokinit(sep_chars);
  436.  
  437.     if (ntok<2) fname = file_name;
  438.     strcpy(file_name,fname);
  439.  
  440.     if (ntok>2) {
  441.      if (range_def(range,&rr)) range_next(&rr);
  442.      else  {                   /* range = exp */
  443.          fner("Invalid load range given (%s) \n",range);
  444.          return;
  445.      }
  446.     } else {
  447.      rr.col = 1;  rr.row = 1;
  448.     }
  449.     strlwr(fname);
  450.     fptr = fopen(fname,"r");
  451.     if (fptr==NULL) {
  452.         fner("Could not open (%s) \n",fname);
  453.         return;
  454.     }
  455.     for (;!feof(fptr);) {
  456.         if (fgets(inbuff,7000,fptr)!=NULL) {
  457.             if (load_list) cmd_load_list(&rr,inbuff);
  458.             else cmd_load_line(rr.col,rr.row++,inbuff);
  459.         }
  460.     }
  461.     fclose(fptr);
  462. }
  463.  
  464. static char term_table[256];
  465. m_tokinit(char *termset)
  466. {
  467.     int i;
  468.     for (i=0;i<=255;i++) {
  469.         if (strchr(termset,i)!=NULL) 
  470.             term_table[i]=true;
  471.         else  term_table[i]=false;
  472.     }
  473. }
  474. char *m_tokend(char *s);
  475. char *m_tokend(char *s)
  476. {
  477.     static char *p1,*p2,*ss,*p,savechar;
  478.     if (s!=NULL) {
  479.         ss = s;
  480.         p1 = s;
  481.     } else {
  482.         *p2 = savechar;
  483.         if (*p2 == 0) return NULL;
  484.         p1 = p2+1;
  485.     } 
  486.     for (p=p1; *p != 0; p++) {    /* find a non space */
  487.         if (term_table[*p]==false) break;
  488.     }    
  489.     if (*p==0) return NULL; 
  490.     p1 = p;
  491.     if (*p=='"') {
  492.         p2 = strchr(p+1,'"');
  493.         if (p2==NULL) p2 = p;
  494.         p = ++p2;
  495.     } else {
  496.         for (; *p != 0; p++) {    /* find next space */
  497.             if (term_table[*p]==true) break;
  498.         }
  499.     }
  500.     p2 = p;
  501.     savechar = *p2;
  502.     *p2 = 0;
  503.     return p1;
  504. }
  505.  
  506.  
  507. cmd_load_list(RANGE *r, char *inbuff)
  508. {
  509.     char *s;
  510.     s = m_tokend(inbuff);
  511.     for (;s!=NULL;) {
  512.         load_str(r->col,r->row,s);
  513.         s = m_tokend(NULL);
  514.         range_next(r);
  515.     }
  516.  
  517. }
  518. cmd_load_line(int x, int y, char *inbuff)
  519. {
  520.     char *s;
  521.     s = m_tokend(inbuff);
  522.     for (;s!=NULL;) {
  523.         load_str(x,y,s);
  524.         s = m_tokend(NULL);
  525.         x++;
  526.     }
  527.  
  528. }
  529. load_str(int x, int y, char *s)
  530. {
  531.     static char bb[88];
  532.     if (strcmp(s,".")==0 || strcmp(s,"-")==0 || strcmp(s,"*")==0) clear_cell(x,y);
  533.     else if (isdigit(*s) || *s=='-' || *s=='+' || *s=='.') set_cell(x,y,atof(s));
  534.     else {
  535.         if (strlen(s)>80) {
  536.             strncpy(bb,s,80);
  537.             bb[80] = 0;
  538.             set_scell(x,y,bb);
  539.         } else set_scell(x,y,s);
  540.     }
  541.     show_ifcell(x,y);
  542. }
  543. cmd_save(char *fname, char *range, char *format, int ntok)
  544. {
  545.     RANGE rr;
  546.     static char inbuff[2001];
  547.     static char fmtg[80],buff1[80],savefmtg[80];
  548.     FILE *fptr;
  549.     int lcount=0;
  550.     int i,inlen=0,thelot,k;
  551.     double v;
  552.     char *s;
  553.  
  554.     strlwr(fname);
  555.     trim_data();
  556.     thelot = false;
  557.     if (*range=='-') {s = range; range = format; format = s;}
  558.     if (strcmp(format,"-COMMA")==0) {
  559.         set_outwidth(0);
  560.         between = strdup(", ");
  561.     }
  562.     if (strcmp(format,"-TAB")==0) {
  563.         set_outwidth(0);
  564.         between = strdup("\t");
  565.     }
  566.     if (strcmp(format,"-SPACE")==0) {
  567.         set_outwidth(0);
  568.         between = strdup(" ");
  569.     }
  570.  
  571.     sprintf(fmtg,"%%.%dg",outwidth2);
  572.     if (outwidth1==0 && outwidth2==0) strcpy(fmtg,"%g");
  573.     strcpy(savefmtg,fmtg);
  574.  
  575.     if (ntok<2) fname = file_name;
  576.     if (strcmp(fname,"*")==0) fname = file_name;
  577.     strcpy(file_name,fname);
  578.  
  579.     /* format strings   "%2.3f, " */
  580.     if (ntok<4) format = "%g ";
  581.     if (ntok<3 || strcmp(range," ")==0) thelot = true;
  582.     if (thelot) range = "C1R1";
  583.     if (range_def(range,&rr)) ;
  584.     else  {                   /* range = exp */
  585.         fner("Invalid range given (%s)%d \n",range,strlen(range));
  586.         return;
  587.     }
  588.     if (thelot) rr.c2 = max_x;
  589.     unlink("manip_.bak");
  590.     unlink("manip_.tmp");
  591.     fptr = fopen("manip_.tmp","w");
  592.     if (fptr==NULL) {
  593.         fner("Could not open (%s) \n",fname);
  594.         return;
  595.     }
  596.     for (;range_next(&rr);) {
  597.         if (new_line==true) {
  598.             if (fprintf(fptr,"%s\n",inbuff) <0) printf("Error writing output file\n");
  599.             inbuff[50] = 0;
  600.             if (++lcount==1) fner("{%s} W=%d D=%d {%s}",fname,outwidth1,outwidth2,inbuff);
  601.             inlen = 0;
  602.         }
  603.         if (inlen>0) { strcpy(inbuff+inlen,between); inlen +=strlen(between);}
  604.         get_cellboth(rr.col,rr.row,&v,&s);
  605.         k = rr.col;
  606.         if (k>199) k = 199;
  607.         if (coltype[k]==0) strcpy(fmtg,savefmtg);
  608.         if (coltype[k]==1) strcpy(fmtg,"%f");
  609.         if (coltype[k]==2) strcpy(fmtg,"%e");
  610.         if (s==NULL) {
  611.             i = sprintf(buff1,fmtg,vcell(rr.col,rr.row));
  612.             if (dpoints[k]>0) i = strcpydecimal(inbuff+inlen,buff1,outwidth1,dpoints[k]);
  613.             else i = strcpywidth(inbuff+inlen,buff1,outwidth1);
  614.         } else {
  615.             i = strcpywidth(inbuff+inlen,s,outwidth1);
  616.         }
  617.         inlen += i;
  618.     }
  619.     if (new_line==true) {
  620.         if (fprintf(fptr,"%s\n",inbuff)<0) {
  621.             fner("Error writing output file"); 
  622.             return;
  623.         }
  624.         inbuff[50] = 0;
  625.         if (++lcount==1) fner("Width=%d Precision=%d {%s}",outwidth1,outwidth2,inbuff);
  626.         inlen = 0;
  627.     }
  628.     fclose(fptr);
  629.     if (rename(fname,"manip_.bak")!=0);
  630.     if (rename("manip_.tmp",fname)!=0) fner("Unable to rename manip_.tmp");
  631. }
  632. strcpydecimal(char *dest, char *src, int wid, int dpoints)
  633. {
  634.     /* 123 ,  12.031,  0.0003321 */
  635.     /* dpoints 2 goes too   */
  636.     /* 123.00  12.03  0.00  */
  637.     static char buff[80];
  638.     int i;
  639.  
  640.     strcpy(buff,src);
  641.     if (strchr(buff,'.')==NULL) strcat(buff,".");
  642.     strcat(buff,"0000000000000000000000000000000000");
  643.     *(strchr(buff,'.')+dpoints+1) = 0;
  644.     strcpywidth(dest,buff,wid);
  645.     return strlen(dest);
  646. }
  647. strcpywidth(char *dest, char *src, int wid)
  648. {
  649.     static char buff[80];
  650.     int i;
  651.     i = wid-strlen(src);
  652.     if (i<0) i = 0;
  653.     memset(buff,' ',i);
  654.     buff[i] = 0;
  655.     strcpy(dest,buff);
  656.     strcat(dest,src);
  657.     return strlen(dest);
  658. }
  659. set_outwidth(char *s)
  660. {
  661.     char *ss;
  662.     ss = strchr(s,'.');
  663.     if (ss==NULL) {
  664.         outwidth1 = atoi(s);
  665.         outwidth2 = 8;
  666.     } else {
  667.         *ss++ = 0;
  668.         outwidth1 = atoi(s);
  669.         outwidth2 = atoi(ss);
  670.     }
  671. }
  672. char *unquote(char *s)
  673. {
  674.     char ss[80];
  675.     strcpy(ss,s);
  676.     if (*s=='"') {
  677.     ss[strlen(ss)-1] = 0;
  678.     return strdup(ss+1);
  679.     } else return strdup(ss);
  680. }
  681. cmd_copy(char *src, char *dest, char *ifexp, int ntok, int always)
  682. {
  683.     RANGE ss,dd,savess;
  684.     int c_idx[20], c_val[20], nc, j, isif=false;
  685.     int r_idx[20], r_val[20], nr;
  686.     int cp,vtype,vidx,ddok,ssok;
  687.     double v;
  688.     char outstr[30];
  689.     long pcode[200];
  690.     int plen;
  691.     vtype = 1;
  692.  
  693.     if (ntok>4) isif = true;
  694.     if (!range_def(src,&ss)) { fner("Error in source range {%s} \n",src); return;}
  695.     if (!range_def(dest,&dd)) { fner("Error in destination range {%s} \n",dest); return;}
  696.  
  697.     if (isif) {
  698.         polish(ifexp,(char *) pcode,&plen,&vtype);
  699.         var_find_rc(c_idx,c_val,&nc,'C');
  700.         var_find_rc(r_idx,r_val,&nr,'R');
  701.     }
  702.     ddok = range_next(&dd);
  703.     ssok = range_next(&ss);
  704.     savess = ss;
  705.     for (;ssok && ddok;) {
  706.         if (isif) {
  707.             cp = 0;
  708.             eval_setxy(ss.col,ss.row);
  709.             eval_setxyd(dd.col,dd.row);
  710.             for (j=0;j<nc;j++) {
  711.                 var_set(c_idx[j],vcell(c_val[j],ss.row));
  712.             }
  713.             for (j=0;j<nr;j++) {
  714.                 var_set(r_idx[j],vcell(ss.col,r_val[j]));
  715.             }
  716.             eval(pcode,&cp,&v,outstr,&vtype);
  717.         }
  718.         if (v==true || !isif) {
  719.             copy_cell(ss.col,ss.row,dd.col,dd.row);
  720.             show_ifcell(dd.col,dd.row);
  721.             ddok = range_next(&dd);
  722.         } else if (always) ddok = range_next(&dd);
  723.         if (always!=2) ddok = true;
  724.         ssok = range_next(&ss);
  725.         if (!ssok && always==2) {
  726.             ss = savess;    ssok = true;
  727.         }
  728.     }
  729. }
  730. int gen_next(char *pat, double *v);
  731. cmd_generate(char *patx, char *dest, int ntok)
  732. {
  733.     int left,right;
  734.     RANGE rr;
  735.     static char pat[188];
  736.     static char middle[80];
  737.     double v;
  738.     int i,j;
  739.  
  740.     strcpy(pat,patx);
  741.     if (strchr(pat,'(')==NULL) {fner("Expecting left bracket"); return;}
  742.     if (strchr(pat,')')==NULL) {fner("Expecting left bracket"); return;}
  743.     if (ntok!=3) {fner("Expecting (GEN pattern range)"); return;}
  744.  
  745.     if (pat[0]=='(') {strcpy(pat,"1"); strcat(pat,patx);}
  746.     if (pat[strlen(pat)-1] == ')') strcat(pat,"1");
  747.     left = atoi(strtok(pat,"()"));
  748.     strcpy(middle,strtok(NULL,"()"));
  749.     right = atoi(strtok(NULL,"()"));
  750.     if (left==0) left = 1;
  751.     if (right==0) right = 1;
  752.     if (!range_def(dest,&rr))  {fner("Invalid range given (%s) \n",dest); return;}
  753.     for (i=0;i<right;i++) {
  754.       gen_next(middle,&v);
  755.       for (;gen_next(NULL,&v);) {
  756.         for (j=0;j<left;j++) {
  757.         range_next(&rr);
  758.         set_cell(rr.col,rr.row,v);
  759.         show_ifcell(rr.col,rr.row);
  760.         }
  761.       }
  762.     }
  763. }
  764. gen_next(char *pat, double *v)
  765. {
  766.     static char *s,p[200];
  767.     static double v1,v2,v3;
  768.     static int instep;
  769.     char *c1,*c2;
  770.     if (pat!=NULL) {
  771.         strcpy(p,pat);
  772.         s = strtok(p,",");
  773.         return true;
  774.     }
  775.     if (instep) {
  776.            v1 += v3;
  777.            *v = v1;
  778.            if (v1<=v2) return true;
  779.            else instep = false;
  780.     }
  781.     if (s==NULL) return false;
  782.     c2 = c1 = strchr(s,':');
  783.     if (c1!=NULL) c2 = strchr(c1+1,':');
  784.  
  785.     if (c1==NULL) {
  786.         *v = atof(s);
  787.         s = strtok(NULL,",");
  788.         return true;
  789.     }
  790.     v1 = atof(s);
  791.     v2 = atof(c1+1);
  792.     if (c2==NULL) v3 = 1; else v3 = atof(c2+1);
  793.     *v = v1;
  794.     instep = true;
  795.     s = strtok(NULL,",");
  796.     if (v1>v2) return false;
  797.     return true;
  798. }
  799. int c_idx[20], c_val[20], ncc;
  800. int r_idx[20], r_val[20], nrr;
  801. long cpcode[200];
  802. cmd_polish(char *exp)
  803. {
  804.     int cp,vtype,vidx,ddok,ssok;
  805.     int plen;
  806.     vtype = 1;
  807.  
  808.     polish(exp,(char *) cpcode,&plen,&vtype);
  809.     var_find_rc(c_idx,c_val,&ncc,'C');
  810.     var_find_rc(r_idx,r_val,&nrr,'R');
  811. }
  812. cmd_eval(int x1, int y1, double *v)
  813. {
  814.     int cp,vtype,vidx,ddok,ssok,j;
  815.     char outstr[30];
  816.     vtype = 1;
  817.  
  818.     cp = 0;
  819.     eval_setxy(x1,y1);
  820.     eval_setxyd(x1,y1);
  821.     for (j=0;j<ncc;j++) {
  822.         var_set(c_idx[j],vcell(c_val[j],y1));
  823.     }
  824.     for (j=0;j<nrr;j++) {
  825.         var_set(r_idx[j],vcell(x1,r_val[j]));
  826.     }
  827.     eval(cpcode,&cp,v,outstr,&vtype);
  828. }
  829. cmd_delete(char *range, char *ifexp, int ntok)
  830. {
  831.     RANGE rr;
  832.     double v;
  833.     int isif,i,j,wid,w;
  834.     if (ntok>2) isif = true; else isif = false;
  835.     if (!range_def(range,&rr)) { fner("Error in range {%s} \n",range); return;}
  836.  
  837.     if (isif) cmd_polish(ifexp);
  838.     range_next(&rr);
  839.     if (rr.colfirst) {
  840.         w = rr.c2-rr.c1+1;
  841.         wid = max_x-rr.c1;
  842.     } else {
  843.         w = rr.r2-rr.r1+1;
  844.         wid = max_y-rr.r1;
  845.     }
  846.     for (;;) {
  847.         if (rr.colfirst) {
  848.           if (isif) cmd_eval(rr.col,rr.row,&v);
  849.           if (v==true || !isif) {
  850.             for (j=0;j<wid; j++) {
  851.               copy_cell(rr.col+j+w,rr.row,rr.col+j,rr.row);
  852.               show_ifcell(rr.col+j,rr.row);
  853.             }
  854.             for (j=0;j<w;j++) {
  855.               clear_cell(rr.c2+wid-j,rr.row);
  856.               show_ifcell(rr.c2+wid-j,rr.row);
  857.             }
  858.           }
  859.           rr.row++;
  860.           if (rr.row>rr.r2) break;
  861.         } else {
  862.           if (isif) cmd_eval(rr.col,rr.row,&v);
  863.           if (v==true || !isif) {
  864.             for (j=0;j<wid; j++) {
  865.               copy_cell(rr.col,rr.row+j+w,rr.col,rr.row+j);
  866.               show_ifcell(rr.col,rr.row+j);
  867.             }
  868.             for (j=0;j<w;j++) {
  869.               clear_cell(rr.col,rr.r2+wid-j);
  870.               show_ifcell(rr.col,rr.r2+wid-j);
  871.             }
  872.           }
  873.           rr.col++;
  874.           if (rr.col>rr.c2) break;
  875.         }
  876.     }
  877. }
  878. int oncol;
  879. cmd_sort(char *range, char *ifexp, int ntok)
  880. {
  881.     RANGE rr;
  882.     double v;
  883.     int *pnt;
  884.     int isif,i,j,wid,w,c,savemax;
  885.     if (ntok<3) {fner("Expecting   SORT  c1c2  ON <exp> "); return; }
  886.     if (!range_def(range,&rr)) { fner("Error in range {%s} \n",range); return;}
  887.  
  888.     savemax = max_x;
  889.     oncol = max_x + 1;
  890.     cmd_polish(ifexp);
  891.     range_next(&rr);
  892.     if (ntok==5) {
  893.       for (i=rr.r1;i<=rr.r2;i++) {
  894.         copy_cell(rr.c1,i,oncol,i);
  895.       }
  896.     } else {
  897.       for (i=rr.r1;i<=rr.r2;i++) {
  898.         cmd_eval(rr.c1,i,&v);
  899.         set_cell(oncol,i,v);
  900.       }
  901.     }
  902.     pnt = calloc(max_y+2,sizeof(int));
  903.     if (pnt==NULL) {fner("Not enough memory to sort"); return;}
  904.     for (i=0;i<=max_y+1;i++) pnt[i] = i;
  905.     for (i=rr.r1+1;i<=rr.r2;i++) {
  906.         if (cell_greater(oncol,pnt[i-1],oncol,pnt[i])) {
  907.             sort_shuffle(i,rr.r1,pnt);
  908.         }
  909.     }
  910.     for (c=rr.c1; c<=rr.c2; c++) {
  911.         for (j=rr.r1;j<=rr.r2;j++) {
  912.             copy_cell(c,pnt[j],oncol,j);
  913.         }
  914.         for (j=rr.r1;j<=rr.r2;j++) {
  915.             copy_cell(oncol,j,c,j);
  916.             show_ifcell(c,j);
  917.         }
  918.     }
  919.     for (j=1;j<=max_y;j++) clear_cell(oncol,j);
  920.     max_x = savemax;
  921. }
  922. sort_shuffle(int i, int r1, int *pnt)
  923. {
  924.     int ins,j,x;
  925.     ins = r1;
  926.     for (j=i-1;j>=r1;j--) {
  927.         if (cell_greater(oncol,pnt[i],oncol,pnt[j])) {
  928.             ins = j + 1;
  929.             break;
  930.         }
  931.     }
  932.     x = pnt[i];
  933.     for (j=i;j>=ins;j--) pnt[j] = pnt[j-1];
  934.     pnt[ins] = x;
  935. }
  936. cmd_insert(char *range)
  937. {
  938.     RANGE rr;
  939.     double v;
  940.     int isif,i,j,wid,w,cwid,cw,rwid,rw;
  941.     if (!range_def(range,&rr)) { fner("Error in range {%s} \n",range); return;}
  942.  
  943.     range_next(&rr);
  944.     cw = rr.c2-rr.c1+1;
  945.     cwid = max_x-rr.c1+1;
  946.     rw = rr.r2-rr.r1+1;
  947.     rwid = max_y-rr.r1+1;
  948.     for (;;) {
  949.         if (rr.colfirst) {
  950.             for (j=cwid-1;j>=0; j--) {
  951.               copy_cell(rr.col+j,rr.row,rr.col+j+cw,rr.row);
  952.               show_ifcell(rr.col+j+cw,rr.row);
  953.             }
  954.             for (j=0;j<cw;j++) {
  955.               clear_cell(rr.c1+j,rr.row);
  956.               show_ifcell(rr.c1+j,rr.row);
  957.             }
  958.             rr.row++;
  959.             if (rr.row>rr.r2) break;
  960.         } else {
  961.             for (j=rwid-1;j>=0; j--) {
  962.               copy_cell(rr.col,rr.row+j,rr.col,rr.row+j+rw);
  963.               show_ifcell(rr.col,rr.row+j+rw);
  964.             }
  965.             for (j=0;j<rw;j++) {
  966.               clear_cell(rr.col,rr.r1+j);
  967.               show_ifcell(rr.col,rr.r1+j);
  968.             }
  969.             rr.col++;
  970.             if (rr.col>rr.c2) break;
  971.         }
  972.     }
  973. }
  974. cmd_data(char *range)
  975. {
  976.     RANGE rr;
  977.     static char ans[155];
  978.     int cmd;
  979.     if (!range_def(range,&rr)) {
  980.         fner("Invalid range given (%s)%d \n",range,strlen(range));
  981.         return;
  982.     }
  983.     for (;;) {
  984.         range_next(&rr);
  985.         mjl_flush();
  986. xxx:        set_newxy(rr.col,rr.row);
  987.         if (!iserr) fner("Press ^Z or ESC when data entry finished\n");
  988.         read_command(&cmd,ans,"DATA% ");
  989.         if (cmd==eescape || cmd==equit) break;
  990.         if (cmd!=0) {
  991.             do_arrow(cmd);
  992.             rr.col = curx; rr.row = cury;
  993.             goto xxx;
  994.         } else {
  995.           if (isnumber(ans)) {
  996.             set_cell(curx,cury,atof(ans));
  997.           } else {
  998.             set_scell(curx,cury,ans);
  999.           }
  1000.           show_cellwide(curx,cury);
  1001.         }
  1002.     }
  1003. }
  1004. swap_def(char *s, RANGE *r)
  1005. {
  1006.     char *s1;
  1007.     char rr,cc;
  1008.  
  1009.     strip_colon(s);
  1010.  
  1011.     r->c1 = r->c2 = r->r1 = r->r2 = r->row = r->col = 0;
  1012.  
  1013.     if (*s=='C') {cc='C'; rr='R'; r->colfirst = true;}
  1014.     else if (*s=='R') {cc='R'; rr='C'; r->colfirst = false;}
  1015.     else return false;
  1016. /*    c1   c1r1r10   c3c4r7 c3r7  c3c4r1r2 |   r1r2c1c3   c3r7  r2*/
  1017.  
  1018.     s1 = range_int(s,&(r->c1));
  1019.     if (*s1==cc) {
  1020.         s1 = range_int(s1,&r->c2);
  1021.     }
  1022.     if (*s1==rr) {
  1023.         s1 = range_int(s1,&r->r1);
  1024.         if (*s1==cc) {
  1025.             s1 = range_int(s1,&r->c2);
  1026.         }
  1027.         if (*s1==rr) {
  1028.             s1 = range_int(s1,&r->r2);
  1029.         }
  1030.         if (*s1==cc) {
  1031.             s1 = range_int(s1,&r->c2);
  1032.         }
  1033.     }
  1034.     if (!r->colfirst) {
  1035.         swapint(&r->c1,&r->r1);
  1036.         swapint(&r->c2,&r->r2);
  1037.     }
  1038.     if (*s1!=0) return false;
  1039.     return true;
  1040. }
  1041. cmd_swap(char *range)
  1042. {
  1043.     RANGE rr;
  1044.     int i,j;
  1045.     if (!swap_def(range,&rr)) {
  1046.         fner("Invalid range given (%s) expecting c1c2 or r1r2 \n",range);
  1047.         return;
  1048.     }
  1049.     if (rr.colfirst) {
  1050.       j = max_y;
  1051.       if (rr.r2!=0) j = rr.r2;
  1052.       if (rr.c1==0 || rr.c2==0) {fner("Invalid range, expected c1c2\n"); return;}
  1053.       for (i=1;i<=max_y;i++) {
  1054.         swap_cell(rr.c1,i,rr.c2,i);
  1055.         show_ifcell(rr.c1,i); show_ifcell(rr.c2,i);
  1056.       }
  1057.     } else {
  1058.       j = max_x;
  1059.       if (rr.c2!=0) j = rr.c2;
  1060.       if (rr.r1==0 || rr.r2==0) {fner("Invalid range, expected r1r2\n"); return;}
  1061.       for (i=1;i<=max_x;i++) {
  1062.         swap_cell(i,rr.r1,i,rr.r2);
  1063.         show_ifcell(i,rr.r1); show_ifcell(i,rr.r2);
  1064.       }
  1065.     }
  1066. }
  1067. int add_dotman(char *s);
  1068. FILE *logfile;
  1069. log_open(char *fname)
  1070. {
  1071.     add_dotman(fname);
  1072.     strlwr(fname);
  1073.     logfile = fopen(fname,"w");
  1074.     if (logfile==NULL) {
  1075.         fner("Could not open (%s) \n",fname);
  1076.         return;
  1077.     }
  1078.     islogging = true;
  1079. }
  1080. log_write(char *s)
  1081. {
  1082.     fprintf(logfile,"%s\n",s);
  1083. }
  1084. log_close()
  1085. {
  1086.     if (islogging) fclose(logfile);
  1087.     islogging = false;
  1088. }
  1089. add_dotman(char *s)
  1090. {
  1091.     if (strstr(s,".")==0) strcat(s,".man");
  1092. }
  1093. FILE *atfile;
  1094. at_open(char *fname)
  1095. {
  1096.     add_dotman(fname);
  1097.     strlwr(fname);
  1098.     atfile = fopen(fname,"r");
  1099.     if (atfile==NULL) {
  1100.         fner("Could not open (%s) \n",fname);
  1101.         return;
  1102.     }
  1103.     isating = true;
  1104. }
  1105. at_read(char *s)
  1106. {
  1107.     s[0] = 0;
  1108.     if (feof(atfile)) {
  1109.         fclose(atfile); atfile = NULL; isating = false; return false;
  1110.     }
  1111.     s[0] = 0;
  1112.     if (fgets(s,200,atfile)==NULL) return false;
  1113.     return true;
  1114. }
  1115. strip_colon(char *s)
  1116. {
  1117.     char *ss;
  1118.     ss = s;
  1119.     for (;*s!=0;s++) {
  1120.         if (*s!=':') *ss++ = *s;
  1121.     }
  1122.     *ss++ = 0;
  1123. }
  1124. cmd_parsum(char *range, char *dest)
  1125. {
  1126.     RANGE rr,dd;
  1127.     double total=0;
  1128.     if (!range_def(range,&rr)) { fner("Invalid range given (%s) \n",range); return;}
  1129.     if (!range_def(dest,&dd)) { fner("Invalid destination given (%s) \n",range); return;}
  1130.     for (;range_next(&rr);) {
  1131.         range_next(&dd);
  1132.         total = total + vcell(rr.col,rr.row);
  1133.         set_cell(dd.col,dd.row,total);
  1134.         show_ifcell(dd.col,dd.row);
  1135.     }
  1136. }
  1137. int rangestd(RANGE *rr, double mean, long numrow, double *variance,
  1138.     double *stddev);
  1139.  
  1140. cmd_sum(char *range)
  1141. {
  1142.     RANGE rr,rrsave;
  1143.     double v,var,stddev;
  1144.     char *s;
  1145.     double total=0;
  1146.     long ntot=0;
  1147.     if (!range_def(range,&rr)) { fner("Invalid range given (%s) \n",range); return;}
  1148.     rrsave = rr;
  1149.     for (;range_next(&rr);) {
  1150.         get_cellboth(rr.col,rr.row,&v,&s);
  1151.         if (s==NULL) {
  1152.             total = total + v;
  1153.             ntot++;
  1154.         }
  1155.     }
  1156.     if (ntot>0) {
  1157.         rangestd(&rrsave,total/ntot,ntot,&var,&stddev);
  1158.         printmess("Total %g, Avg %g, sd %g, var %g, Cells %ld \n",total,total/ntot,stddev,var,ntot);
  1159.     } else fner("No values in range\n");
  1160. }
  1161. rangestd(RANGE *rr, double mean, long numrow, double *variance,
  1162.     double *stddev)
  1163. {
  1164.    int i;
  1165.    char *s;
  1166.    double xsqr,v;
  1167.  
  1168.    xsqr = 0.0;
  1169.    if (numrow<2) return;
  1170.    for (;range_next(rr);) {
  1171.       get_cellboth(rr->col,rr->row,&v,&s);
  1172.       if (s==NULL) {
  1173.     xsqr = xsqr + v*v;
  1174.       }
  1175.    }
  1176.    (*variance) = (xsqr - numrow * mean*mean) / (numrow - 1);
  1177.    (*stddev) = sqrt(fabs((*variance)));
  1178. }
  1179.  
  1180. cmd_clear(char *range)
  1181. {
  1182.     RANGE rr;
  1183.     if (!range_def(range,&rr)) { fner("Invalid range given (%s) \n",range); return;}
  1184.     for (;range_next(&rr);) {
  1185.         clear_cell(rr.col,rr.row);
  1186.         show_ifcell(rr.col,rr.row);
  1187.     }
  1188. }
  1189. int fitlsq(RANGE *rrr,int ndata, double *a, double *b, double *siga, double *sigb, double *chi2, double *q);
  1190. cmd_fit(char *range)
  1191. {
  1192.     RANGE rr,rrsave;
  1193.     char *s;
  1194.     double v,a,b,siga,sigb,chi2,q;
  1195.     double total=0;
  1196.     int ntot=0;
  1197.     if (!range_def(range,&rr)) { fner("Invalid range given (%s) \n",range); return;}
  1198.     rr.c2 = rr.c1;
  1199.     rrsave = rr;
  1200.     for (;range_next(&rr);) {
  1201.         get_cellboth(rr.col,rr.row,&v,&s);
  1202.         if (s==NULL) {
  1203.             ntot++;
  1204.         }
  1205.     }
  1206.     if (ntot>0) {
  1207.       fitlsq(&rrsave,ntot,&a,&b,&siga,&sigb,&chi2,&q);
  1208.       printmess("y = %g + b*%g    siga=%g sigb=%g  chi2=%g\n"
  1209.         ,a,b,siga,sigb,chi2);
  1210.     } else fner("No values in range\n");
  1211. }
  1212. static double sqrarg;
  1213. #define SQR(a) (sqrarg=(a),sqrarg*sqrarg)
  1214. fitlsq(RANGE *rrr,int ndata, double *a, double *b, double *siga, double *sigb, double *chi2, double *q)
  1215. {
  1216.     RANGE  rr;
  1217.     double v,x,y,sx=0,sy=0,st2=0,wt,t,ss,sigdat,sxoss;
  1218.     char *s;
  1219.     *b = 0.0;
  1220.     for (rr = *rrr;range_next(&rr);) {
  1221.         get_cellboth(rr.col,rr.row,&x,&s);
  1222.         get_cellboth(rr.col+1,rr.row,&y,&s);
  1223.         if (s==NULL) {
  1224.             sx += x;
  1225.             sy += y;
  1226.         }
  1227.     }
  1228.     ss = ndata;
  1229.     sxoss = sx/ss;
  1230.     for (rr = *rrr;range_next(&rr);) {
  1231.         get_cellboth(rr.col,rr.row,&x,&s);
  1232.         get_cellboth(rr.col+1,rr.row,&y,&s);
  1233.         if (s==NULL) {
  1234.             t=x-sxoss;
  1235.             st2 += t*t;
  1236.             *b += t*y;
  1237.         }
  1238.     }
  1239.     *b /= st2;
  1240.     *a = (sy-sx*(*b))/ss;
  1241.     *siga = sqrt((1.0+sx*sx/(ss*st2))/ss);
  1242.     *sigb = sqrt(1.0/st2);
  1243.     *chi2=0.0;
  1244.     for (rr = *rrr;range_next(&rr);) {
  1245.         get_cellboth(rr.col,rr.row,&x,&s);
  1246.         get_cellboth(rr.col+1,rr.row,&y,&s);
  1247.         if (s==NULL) {
  1248.             *chi2 += SQR(y-(*a)-(*b)*x);
  1249.         }
  1250.     }
  1251.     *q = 1.0;
  1252.     sigdat = sqrt((*chi2)/(ndata-2));
  1253.     *siga *= sigdat;
  1254.     *sigb *= sigdat;
  1255. }
  1256.